----------------------------------------------------------------------------------
----------------------Made by User, his idea, his work-------------------------
-----------
-----------Feel free to use, and to edit it to make whatever you want
-----------But follow some rules:
----------------------------------------------------------------------------------
----------------1. Do not remove any word from this part 
----------------2. Remove the status text                             
----------------3. Do not touch the author name                     
----------------4. Do not change the gl table function names
-------------------------------------END------------------------------------------
----------------------------------------------------------------------------------

-----status, features:

---sphere ( OK )  

---cube ( OK )

---cylinder ( OK ) 

---cone ( OK )  

---circle ( OK )

---square ( OK )  

---square with vertex as arguments ( OK ) 

---triangle ( OK )

---triangle with vertex as arguments ( OK )

---pentagon ( OK )
-----depends on circle. 

---pentagon with vertex as arguments ( NOT IMPLEMENTED )

---hexagon ( OK )
-----depends on circle.

---icosasphere ( OK )

---tetrahedron ( OK )

---octahedron ( OK ) 
-----needs texture coordinates and normals. 

---dodecasphere (NOT IMPLEMENTED)

---piramid (like a tetrahedron, but with 1 more side) ( OK ) 
-----needs texture coordinates and normals. 

---teapot ( NOT IMPLEMENTED)

---torus ( NOT IMPLEMENTED)

---tube ( NOT IMPLEMENTED)

---grid (UNTESTED)

---heightmap grid ( NOT IMPLEMENTED)

---circle grid (NOT IMPLEMENTED)

---circle heightmap grid ( NOT IMPLEMENTED)
function widget:GetInfo()
  return {
    name      = "Drawing Library",
    desc      = "Draws",
    author    = "user, revised by Argh",
    date      = "March 3, 2008",
    license   = "GNU GPL, v2 or later",
    layer     = -1,
    enabled   = true  
  }
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
----some constants

VFS.Include("/widgets/Math_Lib.lua",nil,VFS.RAW) 
local e = Spring.Echo
local A = math.abs
local R = math.rad
local au = 1.618033989

---------------------------------------------------------------------
---------------------------------------------------------------------
-----------------some functions for drawing stuff directly.

local function DrawTriangleF(v1,v2,v3,glmode)
   gl.BeginEnd( glmode, function()
      gl.Vertex(v1[1],v1[2],v1[3])
      gl.Vertex(v2[1],v2[2],v2[3])  
      gl.Vertex(v3[1],v3[2],v3[3])
   end) 
end

local function DrawTriangleV(v1,v2,v3)
   gl.Normal(v1[1],v1[2],v1[3])
   gl.Vertex(v1[1],v1[2],v1[3])
   gl.Normal(v2[1],v2[2],v2[3])
   gl.Vertex(v2[1],v2[2],v2[3])  
   gl.Normal(v3[1],v3[2],v3[3])
   gl.Vertex(v3[1],v3[2],v3[3]) 
end

local function DrawSquareF(v1,v2,v3,v4,glmode) 
   gl.BeginEnd(glmode, function()
      gl.Vertex(v1[1],v1[2],v1[3]) 
      gl.Vertex(v2[1],v2[2],v2[3])  
      gl.Vertex(v3[1],v3[2],v3[3])
      gl.Vertex(v4[1],v4[2],v4[3])
   end)
end

local function DrawSquareV(v1,v2,v3,v4) 
   gl.Vertex(v1[1],v1[2],v1[3]) 
   gl.Vertex(v2[1],v2[2],v2[3])  
   gl.Vertex(v3[1],v3[2],v3[3])
   gl.Vertex(v4[1],v4[2],v4[3])
end

local function DrawPentagonF(v1,v2,v3,v4,v5,glmode) 
   gl.BeginEnd(glmode, function()
      gl.Vertex(v1[1],v1[2],v1[3]) 
      gl.Vertex(v2[1],v2[2],v2[3])  
      gl.Vertex(v3[1],v3[2],v3[3])
      gl.Vertex(v4[1],v4[2],v4[3])
      gl.Vertex(v5[1],v5[2],v5[3])
   end)
end

local function DrawPentagonV(v1,v2,v3,v4,v5) 
   gl.Vertex(v1[1],v1[2],v1[3]) 
   gl.Vertex(v2[1],v2[2],v2[3])  
   gl.Vertex(v3[1],v3[2],v3[3])
   gl.Vertex(v4[1],v4[2],v4[3])
   gl.Vertex(v5[1],v5[2],v5[3])
end

local function DrawVertexArrayV(vnum,array) 
   gl.Vertex(v1[1],v1[2],v1[3]) 
   gl.Vertex(v2[1],v2[2],v2[3])  
   gl.Vertex(v3[1],v3[2],v3[3])
   gl.Vertex(v4[1],v4[2],v4[3])
   gl.Vertex(v5[1],v5[2],v5[3])
end

----create the access for the 'gl' table.

gl.TriangleF     = DrawTriangleF  
gl.TriangleV     = DrawTriangleV  
gl.SquareF       = DrawSquareF  
gl.SquareV       = DrawSquareV  

--------------------------------------------
----------------------------useful functions.

local function SubdivideSmooth3V(v1,v2,v3,subdivision,solid,mul)
   local v12,v23,v31 = {},{},{}   

   local mult = mul
   if (mul < 0.5) then mult = 0.5 end  

   if (subdivision == 0) then
      if (solid == true) then
          DrawTriangleV(v1,v2,v3)
      elseif (solid == false) then
          DrawTriangleF(v1,v2,v3,GL.LINE_LOOP)  
      end       
      return
   end

   for i = 1,3,1 do
      v12[i] = v1[i]*mult + v2[i]*mult
      v23[i] = v2[i]*mult + v3[i]*mult
      v31[i] = v3[i]*mult + v1[i]*mult
   end
 
   SubdivideSmooth3V(v1, v12, v31, subdivision-1, solid, mul*0.9052)
   SubdivideSmooth3V(v2, v23, v12, subdivision-1, solid, mul*0.9052)
   SubdivideSmooth3V(v3, v31, v23, subdivision-1, solid, mul*0.9052)
   SubdivideSmooth3V(v12, v23, v31, subdivision-1, solid, mul*0.9052)
end 

---the subdivide functions takes a polygon as parameter, the number of
---divisions, if it should be solid, and a offset, for every new vertex,
---the offset should usually be set to 0.6 for the best results.
---for no offset, set it to 0.5, it also can be set to values higher
---than 1, but not lower than 0.5.  

gl.SubdivideSmooth3V = SubdivideSmooth3V

-------------------------------------------------------------
-------------------------------------------------------------

local function DrawSphere(rings,segments,radius,mode,x,y,z)
   local anglex = 360/rings
   local anglez = 360/segments
   local rendermode = GL.QUAD_STRIP      
   if (mode == "points") then rendermode = GL.POINTS end  
   if (mode == "lines") then rendermode = GL.LINE_STRIP end 
   if (mode == "quads") then rendermode = GL.QUADS end 
   if (mode == "polygon") then rendermode = GL.POLYGON end 

   for ax=0,360-anglex,anglex do                           
      local x2,z2 = math.cos(R(ax)),math.sin(R(ax))       
      local xx2,zz2 = x2*radius,z2*radius
      
      local axn = ax + anglex; if (axn > 360) then axn = 360 - axn end
      local x2b,z2b = math.cos(R(axn)),math.sin(R(axn))       
      local xx2b,zz2b = x2b*radius,z2b*radius
                   
      gl.BeginEnd(rendermode,function()                                      
         for az=0,360-anglez,anglez do                         
            local x3,z3 = math.cos(R(az)),math.sin(R(az))       
            local xx3,zz3 = x3*radius,z3*radius    
         
            local azn = az + anglez; if (azn > 360) then azn = 360 - azn end
            local x3b,z3b = math.cos(R(azn)),math.sin(R(azn))       
            local xx3b,zz3b = x3b*radius,z3b*radius       
             
            gl.Normal(xx3*A(x2),zz3*A(x2),zz2) 
            gl.TexCoord(1,1)                                  
            gl.Vertex(x+xx3*A(x2),y+zz3*A(x2),z+zz2)             

            gl.Normal(xx3*A(x2b),zz3*A(x2b),zz2b) 
            gl.TexCoord(0,1)  
            gl.Vertex(x+xx3*A(x2b),y+zz3*A(x2b),z+zz2b)             

            gl.Normal(xx3b*A(x2b),zz3b*A(x2b),zz2b)  
            gl.TexCoord(0,0)  
            gl.Vertex(x+xx3b*A(x2b),y+zz3b*A(x2b),z+zz2b)             

            gl.Normal(xx3b*A(x2),zz3b*A(x2),zz2)  
            gl.TexCoord(1,0) 
            gl.Vertex(x+xx3b*A(x2),y+zz3b*A(x2),z+zz2)             
         end
      end) 
   end
end

local function DrawCylinder(segments,radius,suby,mode,x,y,z)
   local anglez = 360/segments
   local rendermode = GL.QUADS   
   local radsy = radius / suby + 1    
   local diameter = radius * 2
   local ddiv = diameter / suby + 1 

   local rads = radius   
   local rads2 = radius - radsy
   
   if (mode == "points") then rendermode = GL.POINTS end  
   if (mode == "lines") then rendermode = GL.LINE_LOOP end 
   if (mode == "quads") then rendermode = GL.QUADS end 
   if (mode == "polygon") then rendermode = GL.POLYGON end 
   for height=0,suby,1 do
      local height2 = height + 1
      local theight = height   
                      
      local radmul = 1  
      local radmul2 = 1

      local ypos = (diameter - rads*2) - radius
      local ypos2 = (diameter - rads2*2) - radius
      rads = (rads - radsy)
      rads2 = (rads2 - radsy)     

      if ((height == 0)or(height == suby)) then radmul = 0 end    

      if (height == 0) then 
         ypos = ddiv - radius
      end  
      if (height == suby) then 
         ypos2 = diameter * 0.5 
      end      
      if (height2 == suby+1) then 
         ypos2 = ypos
      end  
           
      gl.BeginEnd(rendermode,function()                                      
         for az=0,360-anglez,anglez do                         
            local x3,z3 = math.cos(R(az)),math.sin(R(az))       
            local xx3,zz3 = x3*radius,z3*radius    
         
            local azn = az + anglez; if (azn > 360) then azn = 360 - azn end
            local x3b,z3b = math.cos(R(azn)),math.sin(R(azn))       
            local xx3b,zz3b = x3b*radius,z3b*radius       
         
            gl.Normal(x+xx3*radmul,y+ypos,z+zz3*radmul) 
            gl.TexCoord(1,1)                                       
            gl.Vertex(x+xx3*radmul,y+ypos,z+zz3*radmul)             

            gl.Normal(x+xx3*radmul2,y+ypos2,z+zz3*radmul2) 
            gl.TexCoord(1,0)   
            gl.Vertex(x+xx3*radmul2,y+ypos2,z+zz3*radmul2)             

            gl.Normal(x+xx3b*radmul2,y+ypos2,z+zz3b*radmul2) 
            gl.TexCoord(0,0)  
            gl.Vertex(x+xx3b*radmul2,y+ypos2,z+zz3b*radmul2)             

            gl.Normal(x+xx3b*radmul,y+ypos,z+zz3b*radmul) 
            gl.TexCoord(0,1)    
            gl.Vertex(x+xx3b*radmul,y+ypos,z+zz3b*radmul)             
         end
      end) 
   end
end

local function DrawCube(area,mode,x,y,z)
   local rendermode = GL.QUADS       
   if (mode == "points") then rendermode = GL.POINTS end  
   if (mode == "lines") then rendermode = GL.LINE_STRIP end 
   if (mode == "quads") then rendermode = GL.QUADS end 
   if (mode == "polygon") then rendermode = GL.POLYGON end 
   gl.BeginEnd(rendermode,function()  
       gl.Normal(x+(-1*area),y+(-1*area),z+(-1*area))   
       gl.TexCoord(1,1)    
       gl.Vertex(x+(-1*area),y+(-1*area),z+(-1*area))  

       gl.Normal(x+( 1*area),y+(-1*area),z+(-1*area)) 
       gl.TexCoord(0,1)  
       gl.Vertex(x+( 1*area),y+(-1*area),z+(-1*area))  

       gl.Normal(x+( 1*area),y+(-1*area),z+( 1*area))  
       gl.TexCoord(0,0)     
       gl.Vertex(x+( 1*area),y+(-1*area),z+( 1*area))  
 
       gl.Normal(x+(-1*area),y+(-1*area),z+( 1*area)) 
       gl.TexCoord(1,0)    
       gl.Vertex(x+(-1*area),y+(-1*area),z+( 1*area)) 

  
       gl.Normal(x+(-1*area),y+(-1*area),z+( 1*area)) 
       gl.TexCoord(1,1)    
       gl.Vertex(x+(-1*area),y+(-1*area),z+( 1*area))  
 
       gl.Normal(x+( 1*area),y+(-1*area),z+( 1*area))  
       gl.TexCoord(0,1)    
       gl.Vertex(x+( 1*area),y+(-1*area),z+( 1*area)) 

       gl.Normal(x+( 1*area),y+( 1*area),z+( 1*area))   
       gl.TexCoord(0,0)    
       gl.Vertex(x+( 1*area),y+( 1*area),z+( 1*area))   

       gl.Normal(x+(-1*area),y+( 1*area),z+( 1*area))  
       gl.TexCoord(1,0)   
       gl.Vertex(x+(-1*area),y+( 1*area),z+( 1*area))   
 
 
       gl.Normal(x+( 1*area),y+(-1*area),z+(-1*area))  
       gl.TexCoord(1,1)    
       gl.Vertex(x+( 1*area),y+(-1*area),z+(-1*area))  

       gl.Normal(x+( 1*area),y+(-1*area),z+( 1*area))  
       gl.TexCoord(1,0)    
       gl.Vertex(x+( 1*area),y+(-1*area),z+( 1*area))  

       gl.Normal(x+( 1*area),y+( 1*area),z+( 1*area))  
       gl.TexCoord(0,0)   
       gl.Vertex(x+( 1*area),y+( 1*area),z+( 1*area))  

       gl.Normal(x+( 1*area),y+( 1*area),z+(-1*area))  
       gl.TexCoord(0,1)    
       gl.Vertex(x+( 1*area),y+( 1*area),z+(-1*area))  

   
       gl.Normal(x+(-1*area),y+(-1*area),z+(-1*area))  
       gl.TexCoord(1,1)    
       gl.Vertex(x+(-1*area),y+(-1*area),z+(-1*area))  

       gl.Normal(x+(-1*area),y+(-1*area),z+( 1*area)) 
       gl.TexCoord(1,0)    
       gl.Vertex(x+(-1*area),y+(-1*area),z+( 1*area))  

       gl.Normal(x+(-1*area),y+( 1*area),z+( 1*area))  
       gl.TexCoord(0,0)    
       gl.Vertex(x+(-1*area),y+( 1*area),z+( 1*area)) 

       gl.Normal(x+(-1*area),y+( 1*area),z+(-1*area))  
       gl.TexCoord(0,1)    
       gl.Vertex(x+(-1*area),y+( 1*area),z+(-1*area))   


       gl.Normal(x+(-1*area),y+(-1*area),z+(-1*area))   
       gl.TexCoord(1,1)  
       gl.Vertex(x+(-1*area),y+(-1*area),z+(-1*area))   

       gl.Normal(x+( 1*area),y+(-1*area),z+(-1*area))  
       gl.TexCoord(0,1)   
       gl.Vertex(x+( 1*area),y+(-1*area),z+(-1*area))  

       gl.Normal(x+( 1*area),y+( 1*area),z+(-1*area))   
       gl.TexCoord(0,0)       
       gl.Vertex(x+( 1*area),y+( 1*area),z+(-1*area))   

       gl.Normal(x+(-1*area),y+( 1*area),z+(-1*area))   
       gl.TexCoord(1,0)    
       gl.Vertex(x+(-1*area),y+( 1*area),z+(-1*area)) 

 
       gl.Normal(x+(-1*area),y+( 1*area),z+(-1*area)) 
       gl.TexCoord(1,1)    
       gl.Vertex(x+(-1*area),y+( 1*area),z+(-1*area))

       gl.Normal(x+( 1*area),y+( 1*area),z+(-1*area))  
       gl.TexCoord(0,1)    
       gl.Vertex(x+( 1*area),y+( 1*area),z+(-1*area)) 

       gl.Normal(x+( 1*area),y+( 1*area),z+( 1*area))  
       gl.TexCoord(0,0)    
       gl.Vertex(x+( 1*area),y+( 1*area),z+( 1*area))  

       gl.Normal(x+(-1*area),y+( 1*area),z+( 1*area))   
       gl.TexCoord(1,0)  
       gl.Vertex(x+(-1*area),y+( 1*area),z+( 1*area))   
    
   end)
end

local function DrawCircle(subdivision,radius,x,y,z,mode)
   local rendermode = GL.POLYGON       
   if (mode == "points") then rendermode = GL.POINTS end  
   if (mode == "lines") then rendermode = GL.LINE_LOOP end 
   if (mode == "polygon") then rendermode = GL.POLYGON end 
   local sangle = 360/subdivision       
   gl.BeginEnd(rendermode, function()  
      for a = 0,360-sangle,sangle do
          local rads = R(a)  
          local xp,zp = math.cos(rads),math.sin(rads) 
          local xx,zz = xp*radius,zp*radius 
          local tx,tz = (xp+1)/2,(zp+1)/2 

          gl.Normal(x+xx,y,z+zz)
          gl.TexCoord(tx,tz) 
          gl.Vertex(x+xx,y,z+zz)
      end
   end)
end   

local function DrawSquare(area,x,y,z,mode)  
   local rendermode = GL.QUADS   
   if (mode == "points") then rendermode = GL.POINTS end  
   if (mode == "quads") then rendermode = GL.QUADS end 
   if (mode == "lines") then rendermode = GL.LINE_LOOP end 
   if (mode == "polygon") then rendermode = GL.POLYGON end     
   gl.BeginEnd(rendermode, function()  
      gl.Vertex(x+(-1*area),y,z+(-1*area))
      gl.Normal(x+(-1*area),y,z+(-1*area))
      gl.TexCoord(1,1)
      gl.Vertex(x+( 1*area),y,z+(-1*area))
      gl.Normal(x+( 1*area),y,z+(-1*area))
      gl.TexCoord(0,1)
      gl.Vertex(x+( 1*area),y,z+( 1*area))
      gl.Normal(x+( 1*area),y,z+( 1*area))
      gl.TexCoord(0,0)
      gl.Vertex(x+(-1*area),y,z+( 1*area))
      gl.Normal(x+(-1*area),y,z+( 1*area))
      gl.TexCoord(1,0)
   end)
end

local function DrawOctagon(area,x,y,z,mode)
   DrawCircle(8,area,x,y,z,mode)
end

local function DrawHexagon(area,x,y,z,mode)
   DrawCircle(6,area,x,y,z,mode)
end

local function DrawPentagon(area,x,y,z,mode)
   DrawCircle(5,area,x,y,z,mode)
end

local function DrawTriangle(area,x,y,z,mode)
   DrawCircle(3,area,x,y,z,mode)
end

local function DrawTetrahedron(area,x,y,z,mode)
   local a1,a2,a3 = 0,120,240
   local r1,r2,r3 = R(a1),R(a2),R(a3)
   local c1,c2,c3 = math.cos(r1),math.cos(r2),math.cos(r3)     
   local s1,s2,s3 = math.sin(r1),math.sin(r2),math.sin(r3)
   local rx1,rx2,rx3 = c1*area,c2*area,c3*area   
   local rz1,rz2,rz3 = s1*area,s2*area,s3*area   
   local rx4,ry4,rz4 = 0,area,0 
   local harea = area * 0.5
   local rendermode = GL.TRIANGLES
   if (mode == "points") then rendermode = GL.POINTS end  
   if (mode == "lines") then rendermode = GL.LINE_LOOP end 
   if (mode == "triangles") then rendermode = GL.TRIANGLES end 
   if (mode == "polygon") then rendermode = GL.POLYGON end 
   gl.BeginEnd(rendermode, function()
      gl.Vertex(x+rx1,y-harea,z+rz1) 
      gl.Normal(x+rx1,y-harea,z+rz1)
      gl.TexCoord(c1,s1)
      gl.Vertex(x+rx2,y-harea,z+rz2) 
      gl.Normal(x+rx2,y-harea,z+rz2) 
      gl.TexCoord(c2,s2)
      gl.Vertex(x+rx3,y-harea,z+rz3) 
      gl.Normal(x+rx3,y-harea,z+rz3) 
      gl.TexCoord(c3,s3)

      gl.Vertex(x+rx3,y-harea,z+rz3) 
      gl.Normal(x+rx3,y-harea,z+rz3) 
      gl.TexCoord(c1,s1)
      gl.Vertex(x+rx4,(y+ry4)-harea,z+rz4) 
      gl.Normal(x+rx4,(y+ry4)-harea,z+rz4) 
      gl.TexCoord(c2,s2)
      gl.Vertex(x+rx2,y-harea,z+rz2) 
      gl.Normal(x+rx2,y-harea,z+rz2) 
      gl.TexCoord(c3,s3)

      gl.Vertex(x+rx2,y-harea,z+rz2) 
      gl.Normal(x+rx2,y-harea,z+rz2) 
      gl.TexCoord(c1,s1)
      gl.Vertex(x+rx4,(y+ry4)-harea,z+rz4) 
      gl.Normal(x+rx4,(y+ry4)-harea,z+rz4) 
      gl.TexCoord(c2,s2)
      gl.Vertex(x+rx1,y-harea,z+rz1) 
      gl.Normal(x+rx1,y-harea,z+rz1) 
      gl.TexCoord(c3,s3)

      gl.Vertex(x+rx1,y-harea,z+rz1) 
      gl.Normal(x+rx1,y-harea,z+rz1) 
      gl.TexCoord(c1,s1)
      gl.Vertex(x+rx4,(y+ry4)-harea,z+rz4) 
      gl.Normal(x+rx4,(y+ry4)-harea,z+rz4) 
      gl.TexCoord(c2,s2)
      gl.Vertex(x+rx3,y-harea,z+rz3) 
      gl.Normal(x+rx3,y-harea,z+rz3) 
      gl.TexCoord(c3,s3)
   end) 
end

local function DrawIcosasphere(volume,x,y,z,solid,subdivision)
    local icovertex = {
       {  1.0,             0.0,             0.0            },
       {  0.447213595500,  0.894427191000,  0.0            },
       {  0.447213595500,  0.276393202252,  0.850650808354 },
       {  0.447213595500, -0.723606797748,  0.525731112119 },
       {  0.447213595500, -0.723606797748, -0.525731112119 },
       {  0.447213595500,  0.276393202252, -0.850650808354 },
       { -0.447213595500, -0.894427191000,  0.0 },
       { -0.447213595500, -0.276393202252,  0.850650808354 },
       { -0.447213595500,  0.723606797748,  0.525731112119 },
       { -0.447213595500,  0.723606797748, -0.525731112119 },
       { -0.447213595500, -0.276393202252, -0.850650808354 },
       { -1.0,             0.0,             0.0            }
   }
    
   local icofaces = {
      {  0,  1,  2 },
      {  0,  2,  3 },
      {  0,  3,  4 },
      {  0,  4,  5 },
      {  0,  5,  1 },
      {  1,  8,  2 },
      {  2,  7,  3 },
      {  3,  6,  4 },
      {  4, 10,  5 },
      {  5,  9,  1 },
      {  1,  9,  8 },
      {  2,  8,  7 },
      {  3,  7,  6 },
      {  4,  6, 10 },
      {  5, 10,  9 },
      { 11,  9, 10 },
      { 11,  8,  9 },
      { 11,  7,  8 },
      { 11,  6,  7 },
      { 11, 10,  6 }
   }
  
   gl.PushMatrix()
   gl.Translate(x,y,z)
   gl.Scale(volume,volume,volume)
   if (solid == true) then
      gl.BeginEnd(GL.TRIANGLES,function()
         for i = 1,20,1 do  
            local v1 = icofaces[i][1]+1 
            local v2 = icofaces[i][2]+1 
            local v3 = icofaces[i][3]+1 
            SubdivideSmooth3V(icovertex[v1],icovertex[v2],icovertex[v3],subdivision,true,0.605) 
         end
      end)
   elseif (solid == false) then  --it is wire.
      for i = 1,20,1 do  
         local v1 = icofaces[i][1]+1 
         local v2 = icofaces[i][2]+1 
         local v3 = icofaces[i][3]+1 
         SubdivideSmooth3V(icovertex[v1],icovertex[v2],icovertex[v3],subdivision,false,0.605) 
      end 
   end   
   gl.PopMatrix()
end

local function DrawGrid(area,x,y,z,glmode,resx,resz,xy)
   if (xy == false) then
   gl.BeginEnd(glmode, function()
      for xx = -0.5,0.5,1/resx do 
         for zz = -0.5,0.5,1/resz do
            gl.Normal(0,0.7,0) 
            gl.Normal(0,-0.7,0) 
            gl.TexCoord(xx+0.5,zz+0.5)  
            gl.Vertex(xx*area+x,y,zz*area+z)
            gl.Normal(0,0.7,0) 
            gl.Normal(0,-0.7,0) 
            gl.TexCoord(xx+1/resx+0.5,zz+0.5)  
            gl.Vertex((xx+1/resx)*area+x,y,zz*area+z)
            gl.Normal(0,0.7,0) 
            gl.Normal(0,-0.7,0) 
            gl.TexCoord(xx+1/resx+0.5,zz+1/resz+0.5)  
            gl.Vertex((xx+1/resx)*area+x,y,(zz+1/resz)*area+z)        
            gl.Normal(0,0.7,0) 
            gl.Normal(0,-0.7,0) 
            gl.TexCoord(xx+0.5,zz+1/resz+0.5)  
            gl.Vertex(xx*area+x,y,(zz+1/resz)*area+z)
         end    
      end
   end)
   elseif (xy == true) then
   gl.BeginEnd(glmode, function()
      for xx = -0.5,0.5,1/resx do 
         for zz = -0.5,0.5,1/resz do
            gl.Normal(0,0.7,0) 
            gl.Normal(0,-0.7,0) 
            gl.TexCoord(xx+0.5,zz+0.5)  
            gl.Vertex(xx*area+x,zz*area+y,zz)
            gl.Normal(0,0.7,0) 
            gl.Normal(0,-0.7,0) 
            gl.TexCoord(xx+1/resx+0.5,zz+0.5)  
            gl.Vertex((xx+1/resx)*area+x,zz*area+y,zz)
            gl.Normal(0,0.7,0) 
            gl.Normal(0,-0.7,0) 
            gl.TexCoord(xx+1/resx+0.5,zz+1/resz+0.5)  
            gl.Vertex((xx+1/resx)*area+x,(zz+1/resz)*area+y,zz)   
            gl.Normal(0,0.7,0) 
            gl.Normal(0,-0.7,0) 
            gl.TexCoord(xx+0.5,zz+1/resz+0.5) 
            gl.Vertex(xx*area+x,(zz+1/resz)*area+y,zz)
         end    
      end
   end)
   end
end

local function DrawPiramid(area,x,y,z,mode)
   local a1,a2,a3,a4 = 0,90,180,270
   local r1,r2,r3,r4 = R(a1),R(a2),R(a3),R(a4)
   local c1,c2,c3,c4 = math.cos(r1),math.cos(r2),math.cos(r3),math.cos(r4)          
   local s1,s2,s3,s4 = math.sin(r1),math.sin(r2),math.sin(r3),math.sin(r4)   
   local rx1,rx2,rx3,rx4 = c1*area,c2*area,c3*area,c4*area   
   local rz1,rz2,rz3,rz4 = s1*area,s2*area,s3*area,s4*area   
   local rx5,ry5,rz5 = 0,area,0 
   local harea = area * 0.5
   local rendermode = GL.TRIANGLES
   local render2 = GL.QUADS
   if (mode == "points") then rendermode = GL.POINTS; render2 = GL.POINTS end  
   if (mode == "lines") then rendermode = GL.LINE_LOOP; render2 = GL.LINE_LOOP end 
   if (mode == "triangles") then rendermode = GL.TRIANGLES; render2 = GL.QUADS end 
   if (mode == "polygon") then rendermode = GL.POLYGON; render2 = GL.POLYGON end 
   gl.BeginEnd(render2, function()
      gl.Vertex(x+rx1,y-harea,z+rz1) 
      gl.Vertex(x+rx2,y-harea,z+rz2) 
      gl.Vertex(x+rx3,y-harea,z+rz3) 
      gl.Vertex(x+rx4,y-harea,z+rz4) 
   end)
   gl.BeginEnd(rendermode, function()
      gl.Vertex(x+rx1,y-harea,z+rz1) 
      gl.Vertex(x+rx5,(y+ry5)-harea,z+rz5)
      gl.Vertex(x+rx2,y-harea,z+rz2) 

      gl.Vertex(x+rx2,y-harea,z+rz2) 
      gl.Vertex(x+rx5,(y+ry5)-harea,z+rz5)
      gl.Vertex(x+rx3,y-harea,z+rz3) 

      gl.Vertex(x+rx3,y-harea,z+rz3) 
      gl.Vertex(x+rx5,(y+ry5)-harea,z+rz5)
      gl.Vertex(x+rx4,y-harea,z+rz4) 

      gl.Vertex(x+rx4,y-harea,z+rz4) 
      gl.Vertex(x+rx5,(y+ry5)-harea,z+rz5)
      gl.Vertex(x+rx1,y-harea,z+rz1) 
   end)
end

local function DrawOctahedron(area,x,y,z,mode)
   local a1,a2,a3,a4 = 0,90,180,270
   local r1,r2,r3,r4 = R(a1),R(a2),R(a3),R(a4)
   local c1,c2,c3,c4 = math.cos(r1),math.cos(r2),math.cos(r3),math.cos(r4)          
   local s1,s2,s3,s4 = math.sin(r1),math.sin(r2),math.sin(r3),math.sin(r4)   
   local rx1,rx2,rx3,rx4 = c1*area,c2*area,c3*area,c4*area   
   local rz1,rz2,rz3,rz4 = s1*area,s2*area,s3*area,s4*area   
   local rx5,ry5,rz5 = 0,area,0 
   local rx6,ry6,rz6 = 0,-area,0 
   local rendermode = GL.TRIANGLES
   if (mode == "points") then rendermode = GL.POINTS end  
   if (mode == "lines") then rendermode = GL.LINE_LOOP end 
   if (mode == "triangles") then rendermode = GL.TRIANGLES end 
   if (mode == "polygon") then rendermode = GL.POLYGON end 
   gl.BeginEnd(rendermode, function()
      gl.Vertex(x+rx1,y,z+rz1) 
      gl.Vertex(x+rx5,y+ry5,z+rz5)
      gl.Vertex(x+rx2,y,z+rz2) 

      gl.Vertex(x+rx2,y,z+rz2) 
      gl.Vertex(x+rx5,y+ry5,z+rz5)
      gl.Vertex(x+rx3,y,z+rz3) 

      gl.Vertex(x+rx3,y,z+rz3) 
      gl.Vertex(x+rx5,y+ry5,z+rz5)
      gl.Vertex(x+rx4,y,z+rz4) 

      gl.Vertex(x+rx4,y,z+rz4) 
      gl.Vertex(x+rx5,y+ry5,z+rz5)
      gl.Vertex(x+rx1,y,z+rz1) 

      gl.Vertex(x+rx1,y,z+rz1)
      gl.Vertex(x+rx5,y+ry6,z+rz5)
      gl.Vertex(x+rx2,y,z+rz2) 

      gl.Vertex(x+rx2,y,z+rz2) 
      gl.Vertex(x+rx5,y+ry6,z+rz5)
      gl.Vertex(x+rx3,y,z+rz3) 

      gl.Vertex(x+rx3,y,z+rz3) 
      gl.Vertex(x+rx5,y+ry6,z+rz5)
      gl.Vertex(x+rx4,y,z+rz4) 

      gl.Vertex(x+rx4,y,z+rz4) 
      gl.Vertex(x+rx5,y+ry6,z+rz5)
      gl.Vertex(x+rx1,y,z+rz1)

      if (mode == "lines") then
         gl.Vertex(x+rx1,y,z+rz1) 
         gl.Vertex(x+rx2,y,z+rz2) 
         gl.Vertex(x+rx3,y,z+rz3) 
         gl.Vertex(x+rx4,y,z+rz4)
      end   
   end)
end

local function DrawCone(subdivision,suby,radius,mode,x,y,z) 
   local anglez = 360/subdivision
   local rendermode = GL.QUADS       
   local hdiv = radius/(suby+3)
   local rads = radius   
   local rads2 = radius - hdiv
   local diameter = radius * 2
   local ddiv = diameter /(suby+3)  

   if (mode == "points") then rendermode = GL.POINTS end  
   if (mode == "lines") then rendermode = GL.LINE_STRIP end 
   if (mode == "quads") then rendermode = GL.QUADS end 
   if (mode == "polygon") then rendermode = GL.POLYGON end 
   for height=-1,suby,1 do
      local height2 = height + 1 
      local rm,rm2 = 1,1

      local ypos = (diameter - rads*2) - radius
      local ypos2 = (diameter - rads2*2) - radius
      rads = (rads - hdiv)
      rads2 = (rads2 - hdiv)      

      if (height == -1) then 
         rm = 0
         ypos = ddiv - radius
      end  

      gl.BeginEnd(rendermode,function()                                      
         for az=0,360-anglez,anglez do                         
            local x3,z3 = math.cos(R(az)),math.sin(R(az))       
            local xx3,zz3 = x3*radius,z3*radius    
         
            local azn = az + anglez; if (azn > 360) then azn = 360 - azn end
            local x3b,z3b = math.cos(R(azn)),math.sin(R(azn))       
            local xx3b,zz3b = x3b*radius,z3b*radius       
                  
            gl.Normal(((x3+x3b)/2)*((rads*rm)),ypos,((z3+z3b)/2)*((rads*rm)))                            
            gl.Vertex(x+x3*(rads*rm),y+ypos,z+z3*(rads*rm))             
            gl.TexCoord(1,1)    
            gl.Vertex(x+x3*(rads2*rm2),y+ypos2,z+z3*(rads2*rm2))             
            gl.TexCoord(1,0)  
            gl.Vertex(x+x3b*(rads2*rm2),y+ypos2,z+z3b*(rads2*rm2))             
            gl.TexCoord(0,0)  
            gl.Vertex(x+x3b*(rads*rm),y+ypos,z+z3b*(rads*rm))             
            gl.TexCoord(0,1)    
         end
      end) 
   end
end

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
----make copies of the functions for the gl table.

gl.Sphere         = DrawSphere
gl.Cube           = DrawCube
gl.Cylinder       = DrawCylinder
gl.Cone           = DrawCone
gl.Circle         = DrawCircle  
gl.Pentagon       = DrawPentagon 
gl.Hexagon        = DrawHexagon 
gl.Octagon        = DrawHexagon   
gl.Triangle       = DrawTriangle  
gl.Square         = DrawSquare
gl.Tetrahedron    = DrawTetrahedron
gl.Icosasphere    = DrawIcosasphere 
gl.Octahedron     = DrawOctahedron
gl.Piramid        = DrawPiramid 
gl.Grid           = DrawGrid 

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
